package com.xlh.support.quiz.service.impl;

import com.google.common.collect.Lists;
import com.xlh.exception.common.GlobalException;
import com.xlh.support.quiz.dao.QuizMapper;
import com.xlh.support.quiz.dao.helper.QuizAnswerMapperHelper;
import com.xlh.support.quiz.dao.helper.QuizMapperHelper;
import com.xlh.support.quiz.domain.Quiz;
import com.xlh.support.quiz.domain.QuizAnswer;
import com.xlh.support.quiz.po.QuizCreatePO;
import com.xlh.support.quiz.service.QuizManageService;
import com.xlh.support.quiz.service.QuizService;
import com.xlh.support.quiz.vo.QuizVO;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.xlh.support.quiz.constant.QuizPerformanceEnum.*;
import static com.xlh.support.quiz.constant.QuizTypeEnum.JUDGEMENT;
import static com.xlh.support.quiz.constant.QuizTypeEnum.SAQ;

/**
 * @author cheer
 */
@Service
public class QuizManageServiceImpl implements QuizManageService {

    @Autowired
    private QuizService quizService;

    @Autowired
    private QuizMapper quizMapper;

    @Autowired
    private QuizMapperHelper quizMapperHelper;

    @Autowired
    private QuizAnswerMapperHelper quizAnswerMapperHelper;

    @Override
    public List<QuizVO> listQuiz(Long chapterId, Integer pageNumber) {
        List<Quiz> quizzes = quizMapperHelper.listQuiz(chapterId, pageNumber);
        if (CollectionUtils.isEmpty(quizzes)) {
            return new ArrayList<>();
        }

        List<Long> quizIds = quizzes.stream().map(Quiz::getId).collect(Collectors.toList());
        List<QuizAnswer> quizAnswers = quizAnswerMapperHelper.listByQuizIds(quizIds);
        Map<Long, List<QuizAnswer>> answerMap = aggByQuizId(quizAnswers);

        List<QuizVO> quizVOs = new ArrayList<>();
        for (Quiz quiz : quizzes) {
            QuizVO quizVO = QuizVO.builder()
                    .quizId(quiz.getId())
                    .quizName(quiz.getQuizName())
                    .quizType(quiz.getQuizType())
                    .running(quizService.isQuizRunning(quiz.getId()))
                    .build();

            if (Objects.equals(quiz.getQuizType(), JUDGEMENT.getCode())) {
                computeJudgementPerformance(quizVO, answerMap.get(quiz.getId()));
            } else if (Objects.equals(quiz.getQuizType(), SAQ.getCode())) {
                computeSaqPerformance(quizVO, answerMap.get(quiz.getId()));
            }

            quizVOs.add(quizVO);
        }
        return quizVOs;
    }

    @Override
    public void createQuiz(QuizCreatePO quizCreatePO) {
        if (Objects.equals(quizCreatePO.getQuizType(), JUDGEMENT.getCode())) {
            if (quizCreatePO.getJudgementAnswer() == null) {
                throw new GlobalException("判断题答案不能为空");
            }
        }

        Quiz quiz = Quiz.builder()
                .quizName(quizCreatePO.getQuizName())
                .quizType(quizCreatePO.getQuizType())
                .chapterId(quizCreatePO.getChapterId())
                .pageNumber(quizCreatePO.getPageNumber())
                .judgementAnswer(Objects.equals(quizCreatePO.getQuizType(), JUDGEMENT.getCode()) ?
                        quizCreatePO.getJudgementAnswer() : null)
                .build();
        quizMapper.insertSelective(quiz);
    }

    @Override
    @Transactional
    public void deleteQuiz(Long quizId) {
        Quiz quiz = quizMapperHelper.getById(quizId);
        if (quiz == null) {
            throw new GlobalException("题目不存在");
        }

        if (quizService.isQuizRunning(quizId)) {
            throw new GlobalException("提问正在进行中，不能删除");
        }

        quizMapperHelper.deleteById(quizId);
        quizAnswerMapperHelper.deleteByQuizId(quizId);
    }

    @Override
    public void deleteQuizByChapterIds(List<Long> chapterIds) {
        List<Quiz> quizzes = quizMapperHelper.listQuizByChapterIds(chapterIds);
        List<Long> quizIds = quizzes.stream().map(Quiz::getId).collect(Collectors.toList());

        if(CollectionUtils.isNotEmpty(quizIds)){
            quizMapperHelper.deleteByIds(quizIds);
            quizAnswerMapperHelper.deleteByQuizIds(quizIds);
        }

        quizService.deleteRunningQuiz(quizIds, chapterIds);
    }

    private Map<Long, List<QuizAnswer>> aggByQuizId(List<QuizAnswer> quizAnswers) {
        Map<Long, List<QuizAnswer>> answerMap = new HashMap<>();
        for (QuizAnswer answer : quizAnswers) {
            if (answerMap.get(answer.getQuizId()) == null) {
                List<QuizAnswer> answers = Lists.newArrayList(answer);
                answerMap.put(answer.getQuizId(), answers);
            } else {
                answerMap.get(answer.getQuizId()).add(answer);
            }
        }
        return answerMap;
    }

    /**
     * 计算判断题答题情况
     */
    private void computeJudgementPerformance(QuizVO quizVO, List<QuizAnswer> answers) {
        if (CollectionUtils.isEmpty(answers)) {
            quizVO.setAnswerCount(0);
            quizVO.setCorrectPercent("0%");
            return;
        }

        int correctCount = 0;
        for (QuizAnswer answer : answers) {
            if (Objects.equals(answer.getPerformance(), CORRECT.getCode())) {
                correctCount++;
            }
        }

        DecimalFormat df = new DecimalFormat("0%");
        String correctPercent = df.format((double) correctCount / answers.size());

        quizVO.setAnswerCount(answers.size());
        quizVO.setCorrectPercent(correctPercent);
    }

    /**
     * 计算简答题答题情况
     */
    private void computeSaqPerformance(QuizVO quizVO, List<QuizAnswer> answers) {
        if (CollectionUtils.isEmpty(answers)) {
            quizVO.setAnswerCount(0);
            quizVO.setExcellentPercent("0%");
            quizVO.setGoodPercent("0%");
            quizVO.setPoorPercent("0%");
            return;
        }

        int excellentCount = 0;
        int goodCount = 0;
        int poorCount = 0;
        for (QuizAnswer answer : answers) {
            if (Objects.equals(answer.getPerformance(), EXCELLENT.getCode())) {
                excellentCount++;
            } else if (Objects.equals(answer.getPerformance(), GOOD.getCode())) {
                goodCount++;
            } else if (Objects.equals(answer.getPerformance(), POOR.getCode())) {
                poorCount++;
            }
        }

        DecimalFormat df = new DecimalFormat("0%");
        String excellentPercent = df.format((double) excellentCount / answers.size());
        String goodPercent = df.format((double) goodCount / answers.size());
        String poorPercent = df.format((double) poorCount / answers.size());

        quizVO.setAnswerCount(answers.size());
        quizVO.setExcellentPercent(excellentPercent);
        quizVO.setGoodPercent(goodPercent);
        quizVO.setPoorPercent(poorPercent);
    }
}
